package com.leslie.hhcommunity.service.impl;

import com.leslie.hhcommunity.service.DataService;
import com.leslie.hhcommunity.util.RedisKeyUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.RedisStringCommands;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * @author
 * @PackageName:com.leslie.hhcommunity.service.impl
 * @ClassnName:DateServiceImpl
 * @Description:
 * @Date 2022/1/12  14:35
 */
@Service
public class DataServiceImpl implements DataService {

	@Autowired
	RedisTemplate redisTemplate;

	//指定格式
	private SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd");

	/**
	 * 统计UV，将指定IP记录UV
	 *
	 * @param ip
	 */
	@Override
	public void recordUV(String ip) {
		String redisKey = RedisKeyUtil.getUvKey(df.format(new Date()));
		redisTemplate.opsForHyperLogLog().add(redisKey, ip);
	}

	/**
	 * 统计指定日期范围内的UV
	 *
	 * @param startDate
	 * @param endDate
	 * @return
	 */
	@Override
	public long calculateUV(Date startDate, Date endDate) {
		if (startDate == null || endDate == null) {
			throw new IllegalArgumentException("参数不能为空");
		}
		//整理该日期范围内的key
		List<String> keyList = new ArrayList<>();
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(startDate);
		while (!calendar.getTime().after(endDate)) {
			String key = RedisKeyUtil.getUvKey(df.format(calendar.getTime()));
			keyList.add(key);
			calendar.add(calendar.DATE, 1);
		}
		//合并这些数据
		String redisKey = RedisKeyUtil.getUvKey(df.format(startDate), df.format(endDate));
		redisTemplate.opsForHyperLogLog().union(redisKey, keyList.toArray());
		//统计数据
		return redisTemplate.opsForHyperLogLog().size(redisKey);
	}

	/**
	 * 统计DAU，将指定用户id计入DAU
	 *
	 * @param userId
	 */
	@Override
	public void recordDAU(int userId) {
		String redisKey = RedisKeyUtil.getDauKey(df.format(new Date()));
		redisTemplate.opsForValue().setBit(redisKey, userId, true);
	}

	/**
	 * 统计指定日期范围的DAU
	 *
	 * @param startDate
	 * @param endDate
	 * @return
	 */
	@Override
	public long calculateDAU(Date startDate, Date endDate) {
		if (startDate == null || endDate == null) {
			throw new IllegalArgumentException("参数不能为空");
		}
		//整理该日期范围内的key
		List<byte[]> keyList = new ArrayList<>();
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(startDate);
		while (!calendar.getTime().after(endDate)) {
			String key = RedisKeyUtil.getDauKey(df.format(calendar.getTime()));
			keyList.add(key.getBytes());
			calendar.add(calendar.DATE, 1);
		}
		//合并这些数据,or运算
		return (long) redisTemplate.execute(new RedisCallback() {
			@Override
			public Object doInRedis(RedisConnection connection) throws DataAccessException {
				String redisKey = RedisKeyUtil.getDauKey(df.format(startDate), df.format(endDate));
				connection.bitOp(RedisStringCommands.BitOperation.OR,
						redisKey.getBytes(),keyList.toArray(new byte[0][0]));
				return connection.bitCount(redisKey.getBytes());
			}
		});
	}
}
